package cn.edu.hust.cm.lib;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URI;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

/**
 * 对小的文本文件进行包装, 方便进行文本操作. 注意, 如果用于大的文本文件, 可能存在性能问题及内存占用过高的问题
 * 
 * @author 陈明
 * 
 */
public class TextFileWrapper implements Iterable<String> {
	protected File file;
	protected List<String> lines;
	protected InputStream in;

	public TextFileWrapper(File parent, String child) throws IOException {
		file = new File(parent, child);
		init();
	}

	public TextFileWrapper(String parent, String child) throws IOException {
		file = new File(parent, child);
		init();
	}

	public TextFileWrapper(String pathname) throws IOException {
		file = new File(pathname);
		init();
	}

	public TextFileWrapper(URI uri) throws IOException {
		file = new File(uri);
		init();
	}

	public TextFileWrapper(InputStream in) throws IOException {
		this.in = in;
		init2();
	}

	// TODO 这里发生过一次重构.
	// 2012-09-27. 现在要设计一个可以查看二进制文件十六进制表示形式的FileWrapper, 发现它适合设计成本类的子类
	// 但是init(), file, in都被写成private了!!!
	protected void init() throws IOException {
		BufferedReader br = null;
		try {
			br = new BufferedReader(new FileReader(file));
			// 防止被更改
			lines = Collections.unmodifiableList(IOUtils.readLines(br,
					Integer.MAX_VALUE));
		} catch (IOException e) {
			JavaLog.e(e.getMessage());
			throw e;
		} finally {
			IOUtils.close(br);
		}
	}

	// TODO 这里发生过一次重构.
	// 2012-09-27. 现在要设计一个可以查看二进制文件十六进制表示形式的FileWrapper, 发现它适合设计成本类的子类
	// 但是init(), file, in都被写成private了!!!
	protected void init2() throws IOException {
		BufferedReader br = new BufferedReader(new InputStreamReader(in));
		try {
			lines = Collections.unmodifiableList(IOUtils.readLines(br,
					Integer.MAX_VALUE));
		} catch (IOException e) {
			JavaLog.e(e.getMessage());
			throw e;
		} finally {
			// XXX 这里不能关闭!!! 不是我的责任
			// IOUtils.close(br);
		}
	}

	@Override
	public Iterator<String> iterator() {
		return lines.iterator();
	}

	/**
	 * 文本文件中是否包含某一行
	 * 
	 * @param str
	 *            一行字符串
	 * @return true, 如果文本文件包含该行
	 */
	public boolean containsLine(String oneLine) {
		return lines.contains(oneLine);
	}

	/**
	 * 文本文件中是否包含某一个单词
	 * 
	 * @param oneWord
	 *            一个单词
	 * @return true, 如果文本文件包含该单词
	 */
	public boolean contains(String oneWord) {
		for (String oneLine : lines) {
			if (oneLine.contains(oneLine)) {
				return true;
			}
		}
		return false;
	}

	/**
	 * 文本文件是否没有任何行
	 * 
	 * @return true, 文本文件不包含任何行
	 */
	public boolean isEmpty() {
		return lines.isEmpty();
	}

	/**
	 * 返回文本文件行数
	 * 
	 * @return 文本文件行数
	 */
	public int lines() {
		return lines.size();
	}

	/**
	 * 返回文本文件中fromIndex到toIndex行的字符串, 包含fromIndex行但不包含toIndex行
	 * 
	 * @param fromIndex
	 * @param toIndex
	 * @throws IndexOutOfBoundsException
	 * @return
	 */
	public List<String> getLines(int fromIndex, int toIndex)
			throws IndexOutOfBoundsException {
		return lines.subList(fromIndex, toIndex);
	}

	/**
	 * 返回文本文件中所有行
	 * 
	 * @return 文本文件中所有行
	 */
	public List<String> getLines() {
		return lines;
	}

	/**
	 * 返回文件文件中第index行
	 * 
	 * @param index
	 *            行号, <b> 注意基数为0</b>
	 * @return 第index行字符串
	 */
	public String getLine(int index) {
		return lines.get(index);
	}
}